/** @noSelfInFile **/
import {GuiType} from "../../../../../controller/model/ControllerOpt";
import {CodeUtil} from "../../../../codeAdapter/CodeUtil";
import Configer from "../../../config/Configer";
import {UIConfigKey} from "../../../../../constant/UIConfig";
import {ColorStr} from "../../../../../type/Type";
import {EventType} from "../../../../../../gui/code/model/GuiModel";
import {frameAdapter, FrameEvent, IFrameAdapter, TextAlign} from "../../adapterInterface/model1/IFrameAdapter";
import {PlayerFactory} from "../../../../PlayerFactory";
import {PlayerModel} from "../../../adapterModel/model4/PlayerModel";

class FrameHandle {
    id: string;
    currentFrame: number;
    backFrame: number;
    borderFrame: number;
    maskFrame: number;
    textFrame: number;
    buttonFrame: number;
    eventMap: {};
}


interface EventObj {
    onMouseEnter: (this: void, pos: FrameEvent) => boolean
    onMouseLeave: (this: void, pos: FrameEvent) => boolean
    onMouseDown: (this: void, pos: FrameEvent) => boolean
    onMouseWheel: (this: void, pos: FrameEvent) => boolean
    onMouseUp: (this: void, pos: FrameEvent) => boolean
}

export enum CenterType {
    before = 0,
    center = 16,
    behind = 32,
}

enum DefaultFrameType {
    back = 0,
    frame,
}

export class FrameEventUtil {
    static clickOnUi  = false;
    static _eventMap: Map<number, EventObj> = new Map();
    static clickEvent: (this: void, pos: FrameEvent) => boolean;
    static wheelEvent: (this: void, pos: FrameEvent) => boolean;
    static registGuiCodeScript(frame: number, type: EventType, callBack: (pos: FrameEvent) => boolean) {
        let currentEventMap = FrameEventUtil._eventMap.get(frame);
        if (currentEventMap) {
        } else {
            currentEventMap = { onMouseEnter: null, onMouseLeave: null, onMouseDown: null, onMouseUp: null, onMouseWheel: null };
            FrameEventUtil._eventMap.set(frame, currentEventMap);
        }
        switch (type) {
            case EventType.onMouseRightDown: {
                FrameEventUtil.clickEvent = callBack;
                break;
            }
            case EventType.onMouseWheel: {
                FrameEventUtil.wheelEvent = callBack;
                break;
            }
            case EventType.onMouseDown: {
                currentEventMap.onMouseDown = callBack;
                break;
            }
            case EventType.onMouseUp: {
                currentEventMap.onMouseUp = callBack;
                break;
            }
            case EventType.onMouseEnter:{
                currentEventMap.onMouseEnter = callBack;
                break;
            }
            case EventType.onMouseLeave:{
                currentEventMap.onMouseLeave = callBack;
                break;
            }
        }
    }
    static exeMouseRightDownScript(this: void, pos: FrameEvent) {
        return FrameEventUtil.clickEvent && FrameEventUtil.clickEvent(pos);
    }
    static exeMouseWheelScript(this: void, pos: FrameEvent) {
        return FrameEventUtil.wheelEvent && FrameEventUtil.wheelEvent(pos);
    }
    static exeMouseDownScript(this: void) {
        const triggerFrame = DzGetTriggerUIEventFrame();
        const eventObj = FrameEventUtil._eventMap.get(triggerFrame);
        if (eventObj) {
            const playerModel = frameAdapter.adapter.getTriggerPlayerId()
            eventObj.onMouseDown && eventObj.onMouseDown({ x: 0, y: 0, player: playerModel });
        }
    }
    static exeMouseUpScript(this: void) {
        const triggerFrame = DzGetTriggerUIEventFrame();
        const eventObj = FrameEventUtil._eventMap.get(triggerFrame);
        if (eventObj) {
            const playerModel = frameAdapter.adapter.getTriggerPlayerId()
            eventObj.onMouseUp && eventObj.onMouseUp({ x: 0, y: 0, player: playerModel });
        }
    }
    static exeMouseEnterScript(this: void) {
        const triggerFrame = DzGetTriggerUIEventFrame();
        const eventObj = FrameEventUtil._eventMap.get(triggerFrame);
        if (eventObj) {
            const playerModel = frameAdapter.adapter.getTriggerPlayerId()
            eventObj.onMouseEnter && eventObj.onMouseEnter({ x: 0, y: 0, player: playerModel });
        }
    }
    static exeMouseLeaveScript(this: void) {
        const triggerFrame = DzGetTriggerUIEventFrame();
        const eventObj = FrameEventUtil._eventMap.get(triggerFrame);
        if (eventObj) {
            const playerModel = frameAdapter.adapter.getTriggerPlayerId()
            eventObj.onMouseLeave && eventObj.onMouseLeave({ x: 0, y: 0, player: playerModel });
        }
    }
}

export class FrameAdapter implements IFrameAdapter {

    getRoot() {
        return DzGetGameUI();
    }

    createFrame(id: string, parent: number): any {
        const frames = new FrameHandle()
        frames.id = id;
        frames.currentFrame = DzCreateFrameByTagName(
            GuiType.FRAME,
            id,
            parent,
            '',
            0,
        );

        this.initBorder(frames);
        this.initBack(frames);
        this.initMask(frames);
        this.initText(frames);
        this.initButton(frames);
        return frames;
    }

    setBackImage(frame: FrameHandle, path: string) {
        if (!CodeUtil.isNullOrZero(path)) {
            if (frame.backFrame) {
            } else {
                this.initBack(frame);
            }
            DzFrameSetTexture(frame.backFrame, path, 0);
            DzFrameShow(frame.backFrame, true);
        } else {
            if (frame.backFrame) {
                DzFrameShow(frame.backFrame, false);
            }
        }
    }

    setCenter(frame: FrameHandle, textAlign: TextAlign) {
        if (frame.textFrame) {
            switch (textAlign) {
                case TextAlign.center: {
                    DzFrameSetTextAlignment(frame.textFrame, CenterType.center);
                    break;
                }
                case TextAlign.behind: {
                    DzFrameSetTextAlignment(frame.textFrame, CenterType.behind);
                    break;
                }
            }
        }
    }

    setBorder(frame: FrameHandle, border: string) {
        if (!CodeUtil.isNullOrZero(border)) {
            if (frame.borderFrame) {
            } else {
                this.initBorder(frame)
            }
            DzFrameSetTexture(frame.borderFrame, border, 0)
            DzFrameShow(frame.borderFrame, true);
        } else {
            if (frame.borderFrame) {
                DzFrameShow(frame.borderFrame, false);
            }
        }
    }

    setSize(frame: FrameHandle, height: number, width: number, borderWeight: number, padding: { t: number, r: number, b: number, l: number }) {
        const transBaseX = Configer.getUIConfig(UIConfigKey.transBaseX);
        const transBaseY = Configer.getUIConfig(UIConfigKey.transBaseY);

        if (frame.currentFrame != 0) {
            const tempHeight = height ? (height / transBaseY) : 0;
            const tempBorderWeight = borderWeight ? borderWeight : 0
            const tempWidth = width ? width / transBaseX : 0;

            DzFrameSetSize(frame.currentFrame, tempWidth, tempHeight);

            if (frame.backFrame) {
                DzFrameSetSize(frame.backFrame, tempWidth, tempHeight);
            }

            if (frame.maskFrame) {
                DzFrameSetSize(frame.maskFrame, tempWidth, tempHeight);
            }

            if (frame.textFrame) {
                const paddingL = padding.l ? padding.l : 0;
                const paddingT = padding.t ? padding.t : 0;
                DzFrameSetSize(frame.textFrame, tempWidth - 2 * paddingL / transBaseX, tempHeight - 2 * paddingT / transBaseY);
            }


            if (frame.buttonFrame) {
                DzFrameSetSize(frame.buttonFrame, tempWidth, tempHeight);
            }

            if (frame.borderFrame) {
                const borderW = tempWidth + tempBorderWeight * 2 / transBaseX;
                const borderH = tempHeight + tempBorderWeight * 2 / transBaseY;
                DzFrameSetSize(frame.borderFrame, borderW, borderH);
            }
        }
    }


    setText(frames: FrameHandle, text: string, color: ColorStr) {
        if (!CodeUtil.isNullOrZero(text)) {
            if (frames.textFrame) {
            } else {
                this.initText(frames);
            }
            const tempText = CodeUtil.getColorStr(color, text);
            DzFrameSetText(frames.textFrame, tempText);
            DzFrameShow(frames.textFrame, true);
        } else {
            if (frames.textFrame) {
                DzFrameShow(frames.textFrame, false);
            }
        }
    }

    setTextSizeLimit(frames: FrameHandle, size: number) {
        DzFrameSetTextSizeLimit(frames.currentFrame, size);
    }


    setValue(frames: FrameHandle, value: number) {
        DzFrameSetValue(frames.currentFrame, value);
    }

    setMask(frames: FrameHandle, path: string, flag: number = 0) {
        if (!CodeUtil.isNullOrZero(path)) {
            if (frames.maskFrame) {
            } else {
                this.initMask(frames)
            }
            DzFrameSetTexture(frames.maskFrame, path, flag);
            DzFrameShow(frames.maskFrame, true);
        } else {
            if (frames.maskFrame) {
                DzFrameShow(frames.maskFrame, false);
            }
        }
    }

    setHidden(frames: FrameHandle, flag: boolean, mask: string, backImage: string, border: string, text: string) {
        DzFrameShow(frames.currentFrame, !flag);
        if (frames.buttonFrame) {
            DzFrameShow(frames.buttonFrame, !flag);
        }
        if (flag) {
            if (frames.maskFrame) {
                DzFrameShow(frames.maskFrame, false);
            }

            if (frames.backFrame) {
                DzFrameShow(frames.backFrame, false);
            }

            if (frames.borderFrame) {
                DzFrameShow(frames.borderFrame, false);
            }

            if (frames.textFrame) {
                DzFrameShow(frames.textFrame, false);
            }

        } else {
            if (frames.maskFrame) {
                if (!CodeUtil.isNullOrZero(mask)) {
                    DzFrameShow(frames.maskFrame, true);
                }
            }

            if (frames.backFrame) {
                if (!CodeUtil.isNullOrZero(backImage)) {
                    DzFrameShow(frames.backFrame, true);
                }
            }

            if (frames.borderFrame) {
                if (!CodeUtil.isNullOrZero(border)) {
                    DzFrameShow(frames.borderFrame, true);
                }
            }

            if (frames.textFrame) {
                if (!CodeUtil.isNullOrZero(text)) {
                    // todo testFrame
                    DzFrameShow(frames.textFrame, true);
                }
            }
        }
    }

    cageMouse(frames: FrameHandle, enable: boolean) {
        DzFrameCageMouse(frames.currentFrame, enable);
    }

    clearPoints(frames: FrameHandle) {
        DzFrameClearAllPoints(frames.currentFrame);
    }

    destroy(frames: FrameHandle) {
        DzDestroyFrame(frames.currentFrame);

        if (frames.backFrame) {
            DzDestroyFrame(frames.backFrame)
        }

        if (frames.textFrame) {
            DzDestroyFrame(frames.textFrame)
        }

        if (frames.maskFrame) {
            DzDestroyFrame(frames.maskFrame)
        }
        if (frames.buttonFrame) {
            DzDestroyFrame(frames.buttonFrame)
        }
        if (frames.borderFrame) {
            DzDestroyFrame(frames.borderFrame)
        }
    }

    setAbsPoint(frames: FrameHandle, x: number, y: number, borderWeight: number, margin: { t: number, r: number, b: number, l: number }, padding: { t: number, r: number, b: number, l: number }) {
        const transBaseX = Configer.getUIConfig(UIConfigKey.transBaseX);
        const transBaseY = Configer.getUIConfig(UIConfigKey.transBaseY);

        let tempX = x + margin.l
        let tempY = y + margin.t

        tempX = x ? tempX / transBaseX : 0;
        tempY = y ? (1 - tempY) / transBaseY : 1 / transBaseY;

        const tempBorderWeight = borderWeight ? borderWeight : 0
        DzFrameSetAbsolutePoint(frames.currentFrame, 0, tempX, tempY);

        if (frames.backFrame) {
            DzFrameSetPoint(frames.backFrame, 0, frames.currentFrame, 0, 0, 0);
        }

        if (frames.maskFrame) {
            DzFrameSetPoint(frames.maskFrame, 0, frames.currentFrame, 0, 0, 0);
        }

        if (frames.buttonFrame) {
            DzFrameSetPoint(frames.buttonFrame, 0, frames.currentFrame, 0, 0, 0);
        }
        if (frames.textFrame) {
            DzFrameSetPoint(frames.textFrame, 0, frames.currentFrame, 0, padding.l / transBaseX, -padding.t / transBaseY);
        }
        if (frames.borderFrame) {
            const borderX = tempX - tempBorderWeight / transBaseX;
            const borderY = tempY + tempBorderWeight / transBaseY;
            DzFrameSetAbsolutePoint(frames.borderFrame, 0, borderX, borderY);
        }
    }

    public setAlpha(frames: FrameHandle, alpha: number) {
        if (alpha && alpha >= 0) {
            const realAlpha = alpha * 255;
            DzFrameSetAlpha(frames.currentFrame, realAlpha);
        }
    }

    setEnabled(frames: FrameHandle, flag: boolean) {
        DzFrameSetEnable(frames.currentFrame, flag);
    }

    setFocus(frames: FrameHandle, flag: boolean) {
        DzFrameSetFocus(frames.currentFrame, flag);
    }

    setFontStyle(frames: FrameHandle, filename: string, height: number) {
        if (frames.textFrame) {
            const transBaseY = Configer.getUIConfig(UIConfigKey.transBaseY);
            const fontSize = height / transBaseY;
            // Logger.toastError(`${filename}  ${height}`)
            DzFrameSetFont(frames.textFrame, filename, fontSize, 0);
        }
    }

    setMinMaxValue(frames: FrameHandle, minValue: number, maxValue: number) {
        DzFrameSetMinMaxValue(frames.currentFrame, minValue, maxValue);
    }

    /**
     * 设置模型（支持Sprite、Model、StatusBar）
     */
    setModel(frames: FrameHandle, modelFile: string, modelType: number, flag: number = 0) {
        DzFrameSetModel(frames.currentFrame, modelFile, modelType, flag);
    }

    setScale(frames: FrameHandle, scale: number) {
        if (!CodeUtil.isNullOrZero(scale)) {
            DzFrameSetScale(frames.currentFrame, scale);
        }
    }

    setSpriteAnimate(frames: FrameHandle, animId: number, autocast: boolean) {
        DzFrameSetAnimate(frames.currentFrame, animId, autocast);
    }

    setStepSize(frames: FrameHandle, stepSize: number) {
        DzFrameSetStepValue(frames.currentFrame, stepSize);
    }

    setVertexColor(frames: FrameHandle, color: number) {
        DzFrameSetVertexColor(frames.currentFrame, color);
    }

    setOnMouseRightDown(frames: FrameHandle, callback: (pos: FrameEvent) => boolean, sync = false) {
        if (frames.buttonFrame) {
        } else {
            this.initButton(frames);
        }
        FrameEventUtil.registGuiCodeScript(frames.buttonFrame, EventType.onMouseRightDown, callback)
    }

    setOnMouseDown(frames: FrameHandle, callback: (pos: FrameEvent) => boolean, sync = false) {
        if (frames.buttonFrame) {
        } else {
            this.initButton(frames);
        }

        if (frames.eventMap[EventType.onMouseDown]) {
        } else {
            frames.eventMap[EventType.onMouseDown] = true;
            this.setEventCallback(frames, FRAMEEVENT_CONTROL_CLICK, FrameEventUtil.exeMouseDownScript, false);
        }

        FrameEventUtil.registGuiCodeScript(frames.buttonFrame, EventType.onMouseDown, callback)
    }

    setOnMouseUp(frames: FrameHandle, callback: (pos: FrameEvent) => boolean, sync = false) {
        if (frames.buttonFrame) {
        } else {
            this.initButton(frames);
        }

        if (frames.eventMap[EventType.onMouseUp]) {
        } else {
            frames.eventMap[EventType.onMouseUp] = true;
            this.setEventCallback(frames, FRAMEEVENT_MOUSE_UP, FrameEventUtil.exeMouseUpScript, false);
        }

        FrameEventUtil.registGuiCodeScript(frames.buttonFrame, EventType.onMouseUp, callback)
    }

    setOnDoubleClick(frames: FrameHandle, callback: (pos: FrameEvent) => boolean, sync = false) {
        // FRAMEEVENT_MOUSE_DOUBLECLICK
    }

    setOnMouseEnter(frames: FrameHandle, callback: (pos: FrameEvent) => boolean, sync = false) {
        if (frames.buttonFrame) {
        } else {
            this.initButton(frames);
        }

        if (frames.eventMap[EventType.onMouseEnter]) {
        } else {
            frames.eventMap[EventType.onMouseEnter] = true;
            this.setEventCallback(frames, FRAMEEVENT_MOUSE_ENTER, FrameEventUtil.exeMouseEnterScript, false);
        }

        FrameEventUtil.registGuiCodeScript(frames.buttonFrame, EventType.onMouseEnter, callback)
    }

    setOnMouseLeave(frames: FrameHandle, callback: (pos: FrameEvent) => boolean, sync = false) {
        if (frames.buttonFrame) {
        } else {
            this.initButton(frames);
        }

        if (frames.eventMap[EventType.onMouseLeave]) {
        } else {
            frames.eventMap[EventType.onMouseLeave] = true;
            this.setEventCallback(frames, FRAMEEVENT_MOUSE_LEAVE, FrameEventUtil.exeMouseLeaveScript, false);
        }

        FrameEventUtil.registGuiCodeScript(frames.buttonFrame, EventType.onMouseLeave, callback)
    }

    setOnMouseWheel(frames: FrameHandle, callback: (pos: FrameEvent) => boolean, sync = false) {
        if (frames.buttonFrame) {
        } else {
            this.initButton(frames);
        }
        FrameEventUtil.registGuiCodeScript(frames.buttonFrame, EventType.onMouseWheel, callback)
    }

    setEventCallback(frames: FrameHandle, event: number, callback: () => void, sync = false) {
        if (sync && isAsync) {
            log.errorWithTraceBack("无法在异步中注册同步方法！请在同步方法中执行！")
            return
        }
        switch (event) {
            case EventType.onMouseRightDown:
            case EventType.onMouseWheel: {
                break;
            }
            default: {
                DzFrameSetScriptByCode(frames.buttonFrame, event, callback, sync)
                break;
            }
        }
    }

    getTriggerPlayerId(): PlayerModel {
        const player = DzGetTriggerUIEventPlayer();
        const playerId = GetPlayerId(player);
        const playerModel = PlayerFactory.getInstance().getPlayer(playerId);
        return playerModel;
    }

    initDefaultFrame(bAll: boolean) {

        const mapFrame = DzFrameGetMinimap();


        const mapPos: { x: number, y: number } = Configer.getUIConfig(UIConfigKey.smallMapPos);
        const mapSize: { w: number, h: number } = Configer.getUIConfig(UIConfigKey.smallMapSize);
        if (mapSize.w > 0 && mapSize.h > 0) {
            DzFrameClearAllPoints(mapFrame);
            DzFrameSetSize(mapFrame, mapSize.w, mapSize.h);
        }
        if (mapPos.x > 0 && mapPos.y > 0) {
            DzFrameSetPoint(mapFrame, 6, DzGetGameUI(), 6, mapPos.x, mapPos.y);
            // const smallMapBoard = Configer.getResource(ResourceKey.smallMapBoard)
            // DzSetWar3MapMap(smallMapBoard);
            DzFrameShow(mapFrame, true);
        }
        const sysPos: { x: number, y: number } = Configer.getUIConfig(UIConfigKey.sysPos);
        if (sysPos.x > 0 && sysPos.y > 0) {
            const unitMessage = DzFrameGetUnitMessage();
            DzFrameClearAllPoints(unitMessage);
            DzFrameSetPoint(unitMessage, 6, DzGetGameUI(), 6, sysPos.x, sysPos.y);
            DzFrameShow(unitMessage, true);
        }
        const talkPos: { x: number, y: number } = Configer.getUIConfig(UIConfigKey.talkPos);
        if (talkPos.x > 0 && talkPos.y > 0) {
            const chatMessage = DzFrameGetChatMessage();
            DzFrameClearAllPoints(chatMessage);
            DzFrameSetPoint(chatMessage, 6, DzGetGameUI(), 6, talkPos.x, talkPos.y);
            DzFrameShow(chatMessage, true);
        }


        if (bAll) {
            DzFrameHideInterface();
            DzFrameEditBlackBorders(0, 0);
        } else {
            const mapButtonShow = Configer.getUIConfig(UIConfigKey.mapButtonShow);
            const mapButtonX = Configer.getUIConfig(UIConfigKey.mapButtonX);
            const mapButtonMargin = Configer.getUIConfig(UIConfigKey.mapButtonMargin);

            if (!CodeUtil.isNullOrZero(mapButtonShow)) {
                const buttonMargin = mapButtonMargin
                for (let i = 0; i < 5; i ++) {
                    const button1 = DzFrameGetMinimapButton(i);
                    DzFrameSetPoint(button1, 0, mapFrame, 0, mapButtonX,  -(i * buttonMargin));
                    DzFrameShow(button1, true);
                }
            } else {
                for (let i = 0; i < 5; i ++) {
                    const button1 = DzFrameGetMinimapButton(i);
                    DzFrameClearAllPoints(button1);
                    DzFrameSetPoint(button1, 6, DzGetGameUI(), 6, -0.8, -0.6);
                    DzFrameSetSize(button1, 0, 0);
                    DzFrameShow(button1, false);
                }
            }


            const showArrs: { name: string, id: number, type: DefaultFrameType }[] = [];

            showArrs.push({ name: "InfoPanelIconBackdrop", id: 2, type: DefaultFrameType.back });
            showArrs.push({ name: "InfoPanelIconBackdrop", id: 0, type: DefaultFrameType.back });
            showArrs.push({ name: "InfoPanelIconBackdrop", id: 1, type: DefaultFrameType.back });
            showArrs.push({ name: "SimpleInfoPanelIconHero", id: 0, type: DefaultFrameType.frame });
            showArrs.push({ name: "InfoPanelIconHeroIcon", id: 0, type: DefaultFrameType.frame });
            showArrs.push({ name: "SimpleInfoPanelIconHero", id: 6, type: DefaultFrameType.back });
            showArrs.push({ name: "SimpleHeroLevelBar", id: 0, type: DefaultFrameType.frame });

            for (let i = 0; i < showArrs.length; i++) {
                const hideArr = showArrs[i];
                let frame;
                if (hideArr.type == DefaultFrameType.frame) {
                    frame = DzSimpleFrameFindByName(hideArr.name, hideArr.id);
                } else {
                    frame = DzSimpleTextureFindByName(hideArr.name, hideArr.id);
                }
                // DzFrameClearAllPoints(frame);
                // DzFrameSetPoint(frame, 6, DzGetGameUI(), 6, -0.8, -0.6);
                DzFrameSetSize(frame, 0, 0);
                DzFrameShow(frame, false);
            }

        }
    }


    initText(frames: FrameHandle) {
        const id = frames.id;
        frames.textFrame = DzCreateFrameByTagName(
            GuiType.TEXT,
            id + 'text',
            frames.currentFrame,
            '',
            0,
        );
    }

    initBack(frames: FrameHandle) {
        const id = frames.id;
        frames.backFrame = DzCreateFrameByTagName(
            GuiType.BACKDROP,
            id + 'back',
            frames.currentFrame,
            '',
            0,
        );
    }

    initBorder(frames: FrameHandle) {
        const id = frames.id;
        frames.borderFrame = DzCreateFrameByTagName(
            GuiType.BACKDROP,
            id + 'border',
            frames.currentFrame,
            '',
            0,
        );
    }

    initMask(frames: FrameHandle) {
        const id = frames.id;
        frames.maskFrame = DzCreateFrameByTagName(
            GuiType.BACKDROP,
            id + 'mask',
            frames.currentFrame,
            '',
            0,
        );
    }

    initButton(frames: FrameHandle) {
        const id = frames.id;
        frames.buttonFrame = DzCreateFrameByTagName(
            GuiType.BUTTON,
            id + 'button',
            frames.currentFrame,
            '',
            0,
        );
        frames.eventMap = {};
    }

    stopMouseClick(bool: boolean) {
        FrameEventUtil.clickOnUi = bool;
    }

}
